package org.realogic.cfm.persistence.dialect.db;

import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.session.Configuration;
import org.realogic.cfm.persistence.KParameter;
import org.realogic.cfm.persistence.dialect.AbstractDialect;
import org.realogic.cfm.persistence.query.QueryCondition;

/**
 * MSSQLServer 数据库实现分页方言
 */
public class SQLServerDialect extends AbstractDialect {

	public boolean supportsLimit() {
		return true;
	}

	public String getLimitString(String sql, int offset, int limit) {
		return getSql(sql, offset, limit);
	}

	public String getSelectCountSQL4GroupBy(String sql) {
		return "select count(1) from (" + sql + ") _tmp_size_";
	}

	public String getSql(final String sql, int pageNo, int pageSize) {
		String finalSql = sql;
		int x = pageNo * pageSize;
		String querySqlFirst = "SELECT * FROM ( SELECT TOP " + pageSize + " * FROM ( SELECT TOP " + x;
		String querySqlLastTemp = " ORDER BY id ASC) _tmp1_ ORDER BY id DESC ) as _tmp2_ ORDER BY id ASC";
		String querySqlLast = "";
		if (finalSql.toUpperCase().indexOf("ORDER BY") < 0) {
			querySqlLast = querySqlLastTemp;
		} else {
			querySqlLast = " ORDER BY ";
			int orderby = finalSql.toUpperCase().indexOf("ORDER BY");
			int groupby = finalSql.toUpperCase().indexOf("GROUP BY");
			if (orderby > groupby) {
				groupby = finalSql.length();
			}
			String temp1 = finalSql.substring(finalSql.toUpperCase().indexOf("ORDER BY"), groupby);
			String temp2 = finalSql.substring(finalSql.toUpperCase().indexOf("ORDER BY") + 8, groupby);
			finalSql = finalSql.replaceAll(temp1, " ");
			String[] orderBys = temp2.split(",");
			String orderByASC = "";
			String orderByASC2 = "";
			String orderByDESC = "";
			for (int m = 0; m < orderBys.length; m++) {
				String tempOrderBy = orderBys[m];
				String dot = ",";
				if (m == orderBys.length - 1) {
					dot = "";
				}
				String tempOrderByASC = tempOrderBy;
				String tempOrderByDESC = tempOrderBy;
				if (tempOrderBy.indexOf(".") > 0) {
					tempOrderByASC = "_tmp2_" + tempOrderByASC.substring(tempOrderBy.indexOf("."), tempOrderBy.length());
					tempOrderByDESC = "_tmp1_" + tempOrderByDESC.substring(tempOrderBy.indexOf("."), tempOrderBy.length());
				}
				if (tempOrderBy.toUpperCase().indexOf("DESC") >= 0) {
					orderByASC2 = orderByASC2.concat(tempOrderBy + dot);
					orderByASC = orderByASC.concat(tempOrderByASC + dot);
					int start = tempOrderByDESC.toUpperCase().indexOf("DESC");
					tempOrderByDESC = tempOrderByDESC.substring(0, start) + "ASC";
					orderByDESC = orderByDESC.concat(tempOrderByDESC + dot);
				} else if (tempOrderBy.toUpperCase().indexOf("ASC") >= 0) {
					orderByASC2 = orderByASC2.concat(tempOrderBy + dot);
					orderByASC = orderByASC.concat(tempOrderByASC + dot);
					int start = tempOrderByDESC.toUpperCase().indexOf("ASC");
					tempOrderByDESC = tempOrderByDESC.substring(0, start) + "DESC";
					orderByDESC = orderByDESC.concat(tempOrderByDESC + dot);
				} else {
					orderByASC2 = orderByASC2.concat(tempOrderBy + dot);
					orderByASC = orderByASC.concat(tempOrderByASC + " ASC" + dot);
					orderByDESC = orderByDESC.concat(tempOrderByDESC + " DESC" + dot);
				}
			}
			querySqlLast = querySqlLast.concat(orderByASC2 + ") _tmp1_ ORDER BY ".concat(orderByDESC) + " ) _tmp2_ ORDER BY ".concat(orderByASC));
		}
		String lastSql = querySqlFirst.concat(finalSql.trim().substring(6, finalSql.trim().length()).concat(querySqlLast));
		return lastSql;

	}

	public List<ParameterMapping> newParameterMappings(MappedStatement mappedStatement, BoundSql boundSql, QueryCondition queryCondition, boolean isPaging) {
		Configuration configuration = mappedStatement.getConfiguration();
		ParameterMapping.Builder builder = null;
		List<ParameterMapping> newParameterMappings = new ArrayList<ParameterMapping>(boundSql.getParameterMappings());
		List<KParameter> tmpParamList = queryCondition.getParameterList();
		int size = tmpParamList == null ? 0 : tmpParamList.size();
		KParameter tmpParam = null;
		for (int i = 0; i < size; i++) {
			tmpParam = tmpParamList.get(i);
			builder = new ParameterMapping.Builder(configuration, tmpParam.getName(), tmpParam.geClassClass());
			newParameterMappings.add(builder.build());
			boundSql.setAdditionalParameter(tmpParam.getName(), tmpParam.getValueValue());
		}
		return newParameterMappings;
	}
}
